import sqlite3 
from passlib.hash import sha256_crypt

from error import Duplicate, Missing 
from model.user import User, UserInDB 
from .database import create_curs 


def create_table() -> None:
    """create user table 
    """
    qry = """create table if not exists user(
                username text primary key , 
                disabled text ,
                hashed_password text 
            )"""

    with create_curs() as curs: 
        curs.execute(qry) 
    

def row_to_model(row:tuple) -> User: 
    username, disabled = row
    
    return User(username=username, disabled=disabled)


def create(user: UserInDB) -> User: 
    qry = """insert into user(username, disabled, hashed_password)
              values (:username, :disabled, :hashed_password)
            """
    params = user.model_dump()
    params['hashed_password'] = sha256_crypt.hash(user.hashed_password)
    with create_curs() as curs: 
        try: 
            curs.execute(qry, params) 
        except sqlite3.IntegrityError: 
            raise Duplicate(f'User: {user.username} is exests')

    return get_one(user.username) 


def get_one(username: str) -> User: 
    qry = 'select username, disabled from user ' \
            'where username = :username  ' 
    params = {'username': username} 
    with create_curs() as curs: 
        curs.execute(qry, params) 
        row = curs.fetchone() 
    
    if not row: 
        raise Missing('User: {username} is not found') 
    

    return  User(username=row[0], disabled=row[1])


def get_all() -> list[User]: 
    qry = 'select username, disabled from user' 
    with create_curs() as curs: 
        curs.execute(qry) 

        return [User(username = row[0], disabled= row[1]) for row in curs.fetchall()]


def modify(username: str, user: UserInDB) -> User: 
    get_one(username) 

    qry = 'update user ' \
          ' set username = :username, ' \
                'disabled = :disabled, ' \
                'hashed_password = :hashed_password ' \
                'where username = :username_orgin'
    
    params = user.model_dump()
    hashed_password = sha256_crypt.hash(params['hashed_password'])
    params.update(hashed_password = hashed_password)
    params['username_orgin'] = username 
    
    with create_curs() as curs: 
        try: 
            curs.execute(qry, params) 
        except sqlite3.IntegrityError: 
            raise Duplicate(f'User: {user.username} already exists')
        
    return get_one(user.username) 



def delete(username: str) -> None: 
    with create_curs() as curs: 
        
        curs.execute('delete from user where username = :username', {'username': username})

        if curs.rowcount == 0:
            raise Missing(f'User: {username} is not found') 

def get_one_all(username: str) -> UserInDB: 
    qry = 'select * from user where username = :username' 
    params = {'username': username} 

    with create_curs() as curs: 
        curs.execute(qry, params) 
        row = curs.fetchone() 
    
    if not row: 
        raise Missing(f'User: {username} is not found') 
    
    return UserInDB(username=row[0], disabled=row[1], hashed_password=row[2])


create_table()


    